package com.zq.assistant.utils;

import android.os.AsyncTask;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;

import com.squareup.okhttp.Cache;
import com.squareup.okhttp.CacheControl;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.ResponseBody;
import com.squareup.okhttp.internal.Util;
import com.zq.assistant.func.okhttp.FileTransferListener;
import com.zq.assistant.func.okhttp.download.FileDownloadCallback;
import com.zq.assistant.func.okhttp.download.ProgressResponseBody;
import com.zq.assistant.func.okhttp.upload.FileUploadCallback;
import com.zq.assistant.func.okhttp.upload.ProgressRequestBody;
import com.zq.assistant.func.okhttp.upload.UploadInfo;
import com.zq.assistant.mgr.path.PathManager;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;
import okio.Source;

/**
 * okhttp工具类
 * Created by zhangqiang on 2016/5/6.
 */
public class OKHttpUtils {

    //全局唯一httpClient
    private static final OkHttpClient defaultClient;
    //图片媒体类型
    public static final MediaType MEDIA_TYPE_IMAGE = MediaType.parse("image/*");
    //视频媒体类型
    public static final MediaType MEDIA_TYPE_VIDEO = MediaType.parse("video/*");
    //json
    private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
    //缓存最大值
    private static final long MAX_CACHE_SIZE = 50 * 1024 * 1024;

    static {

        //初始化
        defaultClient = new OkHttpClient();
        defaultClient.setConnectTimeout(10, TimeUnit.SECONDS);
        defaultClient.setReadTimeout(10, TimeUnit.SECONDS);
        defaultClient.setWriteTimeout(10, TimeUnit.SECONDS);

        Cache cache = new Cache(PathManager.get().getHttpCacheDir(),MAX_CACHE_SIZE);
        defaultClient.setCache(cache);
//        defaultClient.networkInterceptors().add(new CacheInterceptor());
    }

    public static void get(String url,Map<String,String> params,Object tag,Callback callback) {

        String suffixURL = makeQueryURL(params);
        if(!TextUtils.isEmpty(suffixURL)){
            url += "?" + suffixURL;
        }

        Request request = createBaseRequestBuilder()
                .get()
                .url(url)
                .tag(tag)
                .build();
        defaultClient.newCall(request).enqueue(callback);
    }

    public static Response getSync(String url,Map<String,String> params,Object tag) throws IOException {

        Request request = createBaseRequestBuilder()
                .get()
                .url(url + "?" + makeQueryURL(params))
                .tag(tag)
                .build();
        return defaultClient.newCall(request).execute();
    }

    /**
     * post提交表单和上传文件，这个是同步请求
     *
     * @param url
     * @param tag
     * @return
     */
    public static Response postFormSync(String url, Map<String, String> formData, Object tag) throws IOException {

        Request request = createBaseRequestBuilder()
                .post(makeFormRequestBody(formData))
                .url(url)
                .tag(tag)
                .build();

        return defaultClient.newCall(request).execute();
    }

    public static void postForm(String url, Map<String, String> formData, Object tag,Callback callback) {

        Request request = createBaseRequestBuilder()
                .post(makeFormRequestBody(formData))
                .url(url)
                .tag(tag)
                .build();

        defaultClient.newCall(request).enqueue(callback);
    }



    /**
     * 取消一个任务
     *
     * @param tag
     */
    public static void cancel(final Object tag) {

        if (Looper.myLooper() == Looper.getMainLooper()) {
            new AsyncTask<String, String, String>() {
                @Override
                protected String doInBackground(String... params) {

                    defaultClient.cancel(tag);
                    return null;
                }
            }.execute();
        } else {
            defaultClient.cancel(tag);
        }
    }


    /**
     * post提交String
     *
     * @param url
     * @param jsonParams
     * @param tag
     * @return
     */
    public static void postJsonString(String url, String jsonParams, Object tag, Callback callback) {

        Request request = createBaseRequestBuilder()
                .url(url)
                .post(RequestBody.create(MEDIA_TYPE_JSON, jsonParams))
                .tag(tag)
                .build();

        Log.i("Test", "=========asyncPostJsonString======jsonParams=" + jsonParams);
        defaultClient.newCall(request).enqueue(callback);
    }

    /**
     * post同步提交String
     *
     * @param url
     * @param jsonParams
     * @param tag
     * @return
     */
    public static Response postJsonStringSync(String url, String jsonParams, Object tag) throws IOException {

        Request request = createBaseRequestBuilder()
                .url(url)
                .post(RequestBody.create(MEDIA_TYPE_JSON, jsonParams))
                .tag(tag)
                .build();

        return defaultClient.newCall(request).execute();
    }

    /**
     * 下载文件
     *
     * @param url
     * @param tag
     * @param savePath
     * @param fileTransferListener
     */
    public static void download(String url, String savePath, Object tag, FileTransferListener fileTransferListener) {

        Request request = createBaseRequestBuilder()
                .get()
                .url(url)
                .tag(tag)
                .build();

        ProgressResponseBody.addFileTransferListener(defaultClient,fileTransferListener)
                .newCall(request)
                .enqueue(new FileDownloadCallback(savePath,fileTransferListener));
    }

    /**
     * 文件上传(用于新的web服务) 60秒未成功就失败
     *
     * @param url         服务器地址
     * @param file        文件对象
     */
    public static void upload(String url, List<File> file, UploadInfo uploadInfo, FileTransferListener fileTransferListener) {

        Request request = createBaseRequestBuilder()
                .url(url)
                .post(ProgressRequestBody.addFileTransferListener(makeMultiPartRequestBody(file, uploadInfo),fileTransferListener))
                .build();

        defaultClient.newCall(request).enqueue(new FileUploadCallback(fileTransferListener));
    }



    private static Request.Builder createBaseRequestBuilder() {

        return new Request.Builder()
                .cacheControl(CacheControl.FORCE_NETWORK)
                .addHeader("AppVersion", AppUtils.VERSION_NAME)
                .addHeader("AppSystem", "ANDROID");
    }

    private static String makeQueryURL(Map<String, String> params) {

        if (params == null) {
            return null;
        }

        StringBuilder path = new StringBuilder();

        Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator();

        while (iterator.hasNext()) {

            Map.Entry<String, String> entry = iterator.next();
            if (entry.getValue() != null) {
                path.append(entry.getKey());
                path.append("=");
                path.append(entry.getValue());
                if (iterator.hasNext()) {
                    path.append("&");
                }
            }
        }
        return path.toString();
    }


    private static RequestBody makeFormRequestBody(Map<String, String> params) {

        FormEncodingBuilder formEncodingBuilder = new FormEncodingBuilder();
        if (params == null || params.isEmpty()) {

            return formEncodingBuilder.build();
        }

        for (Map.Entry<String, String> entry : params.entrySet()) {

            String value = entry.getValue();
            if (value != null) {
                formEncodingBuilder.add(entry.getKey(), value);
            }
        }
        return formEncodingBuilder.build();
    }

    private static RequestBody makeMultiPartRequestBody(List<File> fileList, UploadInfo uploadInfo){

        if (fileList == null || fileList.isEmpty()) {

            throw new NullPointerException("file does not exist");
        }

        String body = JsonUtils.toJsonString(uploadInfo);

        System.out.println("==================" + body);

        MultipartBuilder builder = new MultipartBuilder();
        builder.type(MultipartBuilder.FORM);
        builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"option\""), RequestBody.create(null, body));
        for (File file: fileList ) {
            builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"file\";filename=" + file.getName()), RequestBody.create(null, file));
        }
        return builder.build();
    }

    /**
     * 对图片进行压缩
     */
    private static class ImageCompressRequestBody extends RequestBody {

        private MediaType mediaType;
        private File file;

        ImageCompressRequestBody(MediaType mediaType, File file) {
            this.mediaType = mediaType;
            this.file = file;
            if (this.file == null) throw new NullPointerException("content == null");
        }

        @Override
        public MediaType contentType() {
            return mediaType;
        }

        @Override
        public void writeTo(BufferedSink sink) throws IOException {

            Log.i("Test","=========图片压缩前大小==========" + file.length()/1024 + "kB");

            final File rawFile = file;
            file = FileUtils.getUploadImageFile(file);

            if(file == null || !file.exists()){

                Log.i("Test","=========图片压缩失败==========");
                return;
            }

            Log.i("Test","====是否被压缩==" + !(rawFile == file) + "===图片压缩后大小==========" + file.length()/1024 + "kB");

            Source source = null;
            try {
                source = Okio.source(file);
                sink.writeAll(source);
            } finally {
                Util.closeQuietly(source);
            }
        }
    }

}
